package cn.iocoder.boot.service;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.StringUtil;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Service : 服务类
 * 用于处理实际的业务逻辑。
 */
@Service
@Slf4j
public class BomService {

    @Value("${tmpfilepath}")
    private String tmpFilePath;
    @Value("${s3Url}")
    private String s3Url;
    @Value("${spring.profiles.active}")
    private String activeProfile;
    @Value("${template}")
    private String template;

    @Value("${uploadUrl}")
    private String  uploadUrl;

    @Value("${localFilePath}")
    private String  localFilePath;

    @Value("${workFlowUrl}")
    private String  workFlowUrl;


    // 数据行结束标记字
    final String[] END_ROW_FLAG = new String[]{"申请人", "变更人", "版号"};

    private String getNolineUUid() {
        return java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 12);
    }

    /**
     * 前端页面上传单个文件存至本地
     */
    private String saveToSinglelocalFile(MultipartFile file) {
        String uploadPath = tmpFilePath + getNolineUUid() + "_"; // 防止重复
        String path = uploadPath + file.getOriginalFilename();

        File destination = new File(path);
        if (!destination.getParentFile().exists()) {
            try {
                FileUtils.forceMkdirParent(destination); //使用commons-io的工具类
            } catch (IOException e) {
                log.error("saveTolocalFile异常1", e);
                return null;
            }
        }
        try {
            file.transferTo(destination);//先存本地
        } catch (IOException e) {
            log.error("saveTolocalFile异常2", e);
            return null;
        }
        return destination.getPath(); // .getName();
    }

    /**
     * 写入标准数据
     * @param filename
     * @param newData
     */
    public String createWorkbookWithSheet(String filename, JSONArray newData) {
        // 检查文件是否存在以及是否可读
        File file = new File(filename);
        if (!file.exists()) {
            throw new IllegalArgumentException("文件不存在: " + filename);
        }
        if (!file.canRead()) {
            throw new IllegalArgumentException("文件不可读: " + filename);
        }
        Workbook workbook = ExcelToJsonArray.getWorkbookByFilePath(filename);
        try {
            // 创建新的工作表
            Sheet sheet = workbook.createSheet("标准");
            // 将新创建的 Sheet 移动到最前面
            workbook.setSheetOrder("标准", 0);
            // 写表头
            org.apache.poi.ss.usermodel.Row rowHead = sheet.createRow(0);
            int headIndex = 0;
            for (String key : newData.getJSONObject(0).keySet()) {
                org.apache.poi.ss.usermodel.Cell cell = rowHead.createCell(headIndex);
                headIndex++;
                cell.setCellValue(key);
            }
            // 遍历新数据行
            for (int i = 0; i < newData.size(); i++) {
                JSONObject jsonObject = newData.getJSONObject(i);
                int rowNum = i + 1;
                org.apache.poi.ss.usermodel.Row row = sheet.createRow(rowNum);
                int j = 0;
                for (String key : jsonObject.keySet()) {
                    Object value = jsonObject.get(key);
                    org.apache.poi.ss.usermodel.Cell cell = row.createCell(j);
                    j++;
                    cell.setCellValue(value.toString());
                }
            }
            // 将工作簿写入文件
            try (FileOutputStream fileOut = new FileOutputStream(filename)) {
                workbook.write(fileOut);
            }
        } catch (Exception e) {
            // IO 异常，保留原始异常类型并添加上下文信息
            throw new RuntimeException("IO 错误: " + filename, e);
        } finally {
            if(workbook != null){
                try {
                    workbook.close();
                } catch (IOException e) {
                    log.error("saveTolocalFile异常3", e);
                }
            }
        }
        return null;
    }

    /**
     * 上传文件至S3
     * @param filePath
     * @param userId
     * @param appKey
     * @return
     */
    public String saveFile2S3(String filePath, String userId, String appKey) {
        File file = new File(filePath);
        String contentType = null;
        try {
            contentType = Files.probeContentType(file.toPath());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        log.info("开始文件转存S3方法：saveFile2S3,fileName={},userId={}", file.getName(), userId);
        HttpRequest request = HttpRequest.post(s3Url + "singleUpload3");
        request.form("file", file);
        request.form("appKey", appKey);
        request.form("env", activeProfile);
        request.form("nameBase64", true);
        request.form("userId", userId);
        HttpResponse httpResponse = request.execute();
        JSONObject resultObj = JSONUtil.parseObj(httpResponse.body());
        log.info("完成文件转存S3方法,返回：{}", httpResponse.body());
        if (resultObj.getInt("status") == 0) { //上传成功了
            return resultObj.getJSONObject("data").getStr("value");
        } else {
            log.error("上传失败");
        }

        return null;
    }

    /**
     * 检查处理列关系
     * @param relationObj
     * @param sourceDataList
     */
    private void checkConvert(JSONObject relationObj, JSONArray sourceDataList) {
        // 映射结果的"序号"列有非数字，则去掉映射关系
        String source_column = relationObj.getStr("序号");
        if (!StrUtil.isBlank(source_column) && !("NaN").equals(source_column)) {
            for (Object sourceData : sourceDataList) {
                String value = ((JSONObject) sourceData).getStr(source_column);
                if (!NumberUtil.isNumber(value)) {
                    relationObj.set("序号", "");
                    break;
                }
            }
        }
    }

    private boolean lineContainsEndWord(String line) {
        boolean result = false;
        for (String endWord : END_ROW_FLAG) {
            if (line.contains(endWord)) {
                result = true;
                break;
            }
        }
        return result;
    }

    private String getFirstSheetData(String md_data, String source_coloum) {
        String aryStr[] = md_data.split("## "); //若首行开头即"## "，则会拆分个空字串，故需要判断
        if (aryStr.length >= 2) { // 多个sheet,或单个sheet,但首行可能不是表头情况
            StringBuilder result = new StringBuilder();
            try (BufferedReader reader = new BufferedReader(new StringReader(md_data))) {
                result.append(reader.readLine()).append(System.lineSeparator()); // 读取并丢弃第一行 ## 标记
                String line;
                boolean isFindTableHeader = false;
                while ((line = reader.readLine()) != null) {
                    boolean isneedWrite = true;
//                    String lineFormat = line.replace("| ", "").replace(" |","").replace(" ", "")
//                            .replace("\n","").replace("-","");
//                    String sourceColoumFormat = source_coloum.replace("| ", "").replace(" |","").replace(" ", "")
//                            .replace("\n","").replace("-","");
                    String lineFormat = line.replaceAll("\\|", "").replaceAll(" ", "")
                            .replaceAll("\\n","").replaceAll("-","").replaceAll("NaN","");
                    String sourceColoumFormat = source_coloum.replaceAll("\\|", "").replaceAll(" ", "")
                            .replaceAll("\\n","").replaceAll("-","").replaceAll("NaN","");
                    log.info("lineFormat={},sourceColoumFormat={}", lineFormat, sourceColoumFormat);
                    if (!isFindTableHeader && lineFormat.equals(sourceColoumFormat)) { // 找到表头了
                        result.append(line).append(System.lineSeparator()); // 写入表头
                        result.append("| ");
                        for (int i = 0; i < line.split(" \\|").length; i++) {
                            result.append(" --- |");
                        }
                        result.append(System.lineSeparator());
                        isFindTableHeader = true;
                        isneedWrite = false;
                        log.info("匹配到表头");
                    } else if (line.startsWith("## ") || lineContainsEndWord(line)) { // 找到下一个sheet就停止
                        log.info("匹配到## 结束位");
                        break;
                    }
                    if (isFindTableHeader && !StrUtil.isBlank(line) && isneedWrite) {//表头及数据部分
                        // 可能是表头与数据间隔，跳过不写
                        if(!"".equals(line.replace("|", "").replace(" ", "").replace("-","")
                                .replace("NaN","").replace("\\_",""))) {// | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ | NaN | NaN | NaN | NaN | NaN |
                            result.append(line).append(System.lineSeparator());
                        }
                        // 匹配到了序号列，但序号值非数字，则跳过(适用尾部是非bom物料内容场景BM25030618798)
//                        log.info("写入一行数据:{}", line);
                    }
                }
                return result.toString();
            } catch (IOException e) {
                log.error("getFirstSheetData异常1", e);
                return md_data;
            }
        } else {
            return md_data;
        }
    }

    private void margerLine(JSONArray sourceDataList, String columns_relation) {
        // 判断是否需要合并行(首先用量和位号列映射关系存在)
        JSONObject relationObj = JSONUtil.parseObj(columns_relation);
        String qtyCoumnName = relationObj.getStr("用量");
        String posCoumnName = relationObj.getStr("位号");
//        制造商型号
        String manufacturerModelFieldname = relationObj.getStr("制造商型号");
        if (StrUtil.isBlank(qtyCoumnName) || StrUtil.isBlank(qtyCoumnName) || "NaN".equals(qtyCoumnName) || "NaN".equals(posCoumnName)) {
            return;
        }
        int length = sourceDataList.size();
        for (int i = length - 1; i >= 1; i--) { // 倒序遍历，从最后一行开始向前遍历
            JSONObject currentDataObj = sourceDataList.getJSONObject(i); // 当前行数据
                currentDataObj.set(posCoumnName, currentDataObj.getStr(posCoumnName, "").replace(".", ",")
                        .replace("，", ",").replace(";", ","));
            JSONObject preRowObj = sourceDataList.getJSONObject(i - 1); // 上一行数据
                preRowObj.set(posCoumnName, preRowObj.getStr(posCoumnName, "").replace(".", ",")
                        .replace("，", ",").replace(";", ","));
            Integer qtyValue = preRowObj.getInt(qtyCoumnName, 0); //上一行用量及位号值
            String posValue = preRowObj.getStr(posCoumnName,""); //上一行位号值
            if (StrUtil.isBlank(posValue)) {//位号为空跳过
                continue;
            }
            String[] posValueArray = posValue.split(",");
            // 去掉空值
            String[] filteredArray = Arrays.stream(posValueArray).filter(s -> !s.isEmpty()).toArray(String[]::new);
            if (qtyValue > 0 && filteredArray.length < qtyValue && !posValue.contains("-")) { //进行合并,BM25030718838
                if("NaN".equals(currentDataObj.getStr(manufacturerModelFieldname))
                        || StrUtil.isBlank(currentDataObj.getStr(manufacturerModelFieldname))) { // 制造商型号有不同值，不合并，避免误合并BM25041820178
                    String posValueNew = posValue + "," + currentDataObj.getStr(posCoumnName);
                    posValueNew = posValueNew.replace(",,", ",");
                    preRowObj.set(posCoumnName, posValueNew);
                    sourceDataList.remove(currentDataObj);
                }
            } else if(qtyValue > 0 && filteredArray.length == qtyValue) { // 去掉只有位号的列
                // 用keyset方式遍历currentDataObj对象中的每个元素
                boolean allNan = true;
                for (String key : currentDataObj.keySet()) {
                    if (!key.equals(posCoumnName) && !currentDataObj.getStr(key).equals("NaN")) {
                        allNan = false;
                        break;
                    }
                }
                if (allNan) {
                    sourceDataList.remove(currentDataObj);
                }
            }
        }
    }

    private void deleteEmptyRow(JSONArray sourceDataList) {
        int length = sourceDataList.size();
        for (int i = length - 1; i >= 0; i--) { // 倒序遍历，从最后一行开始向前遍历
            JSONObject jsonObject = sourceDataList.getJSONObject(i); // 当前行数据
//            log.info("jsonObject={}", jsonObject.toStringPretty());
            int validFieldCount = 0;
            for (String key : jsonObject.keySet()) {
//                log.info("key={},value={}", key, jsonObject.getStr(key));
                // 检测到某行有效字段数小于等于2，则丢弃。若把位号删除，则合并列号失效了
                if (!StrUtil.isBlank(jsonObject.getStr(key)) && !"NaN".equals(jsonObject.getStr(key)) && !"0".equals(jsonObject.getStr(key))) {
                    validFieldCount++;
                    if (validFieldCount > 2) {
                        break;
                    }
                }
            }
            if (validFieldCount <= 2) {
                sourceDataList.remove(jsonObject);
            }
        }
    }


    public static JSONObject parseMixedContent(String mixedContent) {
        if (mixedContent == null || mixedContent.trim().isEmpty()) {
            return new JSONObject();
        }

        // 尝试直接解析（如果是标准JSON）
        try {
            return JSONUtil.parseObj(mixedContent);
        } catch (Exception e) {
            // 不是标准JSON，尝试提取JSON部分
        }

        // 寻找可能包含JSON的部分
        int jsonStart = findJsonStart(mixedContent);
        int jsonEnd = findJsonEnd(mixedContent, jsonStart);

        if (jsonStart >= 0 && jsonEnd > jsonStart) {
            String possibleJson = mixedContent.substring(jsonStart, jsonEnd + 1);
            try {
                return JSONUtil.parseObj(possibleJson);
            } catch (Exception e) {
                // 提取的部分仍然不是有效JSON
            }
        }

        return new JSONObject(); // 返回空对象作为兜底
    }

    // 查找JSON开始位置（第一个{）
    private static int findJsonStart(String content) {
        return content.indexOf('{');
    }

    // 从start位置开始查找匹配的}
    private static int findJsonEnd(String content, int start) {
        if (start < 0) return -1;

        int braceCount = 0;
        for (int i = start; i < content.length(); i++) {
            char c = content.charAt(i);
            if (c == '{') {
                braceCount++;
            } else if (c == '}') {
                braceCount--;
                if (braceCount == 0) {
                    return i; // 找到匹配的结束括号
                }
            }
        }
        return -1; // 没有找到匹配的结束括号
    }

    /**
     * columns_relation中映射含 ~ 字段处理
     * @param columns_relation
     * @param source_column
     * @return
     */
    private String replaceColumnsRelation(String columns_relation, String source_column) {
        JSONObject relationObj = JSONUtil.parseObj(columns_relation);
        String[] sourceColumns = source_column.split("\\|");
        for (String key : relationObj.keySet()) {// 遍历每一对列映射关系
            String value = relationObj.getStr(key);
            if (value.contains("~")) {
                String[] split = relationObj.getStr(key).split("~");
                for (String s : split) {
                    if (source_column.contains(" " + s + " ")) {
                        relationObj.set(key, s);
                        break;
                    }
                }
            }
            if (!StrUtil.isBlank(value) && !"NaN".equals(value)) { // 映射列名不为空
                if (!source_column.contains(" " + value + " ")) { // md_data数据中若excel表头含有换行符，则会变成空格代替，而relation中直接把换行符去掉了，导致找不到源字段名
                    for (String s : sourceColumns) {
                        if (value.equals(s.replace(" ", ""))) {
                            relationObj.set(key, s.trim());
                            break;
                        }
                    }
                }
            }
        }
        return relationObj.toStringPretty();
    }

    private String clearErrorRelations(String columns_relation) {
        JSONObject errorRelationObj = getJsonObjCfg("错误映射示例.txt");
        JSONObject ordRelationObj = JSONUtil.parseObj(columns_relation); // AI传递的映射关系
        boolean haveClear = false;
        // 遍历 errorRelationObj
        for (String key : errorRelationObj.keySet()) { // 遍历错误映射关系
            String value = errorRelationObj.getStr(key).replace(" ", "").replace("\n", "");
            String[] errorList = value.split(",");
            // 遍历数组 errorList
            for (String item : errorList) {
                String trimmedItem = item.replace(" ", "").replace("\n", "");
                // 遍历 ordRelationObj
                for (String bbKey : ordRelationObj.keySet()) {
                    String bbValue = ordRelationObj.getStr(bbKey);
                    String trimmedBBKey = bbKey.trim();
                    String trimmedBBValue = bbValue.replace(" ", "").replace("\n", "");
                    // 检查 errorRelationObj 的 key 与 errorList 和 ordRelationObj 的 key 与 value 是否完全相同
                    if (key.equals(trimmedBBKey) && trimmedItem.equals(trimmedBBValue)) {
                        // 将 ordRelationObj 的 value 变为空字符串
                        ordRelationObj.put(bbKey, "");
                        haveClear = true;
                    }
                }
            }
        }
        if (haveClear) {
            log.info("去除错误映射后的json:{}", ordRelationObj.toStringPretty());
        }
        return ordRelationObj.toStringPretty();
    }
    /**
     * BOM文件转换
     * @param columns_relation
     * @param md_data
     * @param source_file
     * @param userId
     * @param appKey
     * @return
     */
    public String bomConvert(String columns_relation, String md_data, MultipartFile source_file,
                             String userId, String appKey, String source_column) {
        // 保存本地文件
        String filename = saveToSinglelocalFile(source_file);
        // columns_relation中映射含 ~ 字段处理
        columns_relation = replaceColumnsRelation(columns_relation, source_column);
        // 去掉错误的映射关系
        columns_relation = clearErrorRelations(columns_relation);
        // 多页、首行非表头的md_data提取表格数据
        md_data = getFirstSheetData(md_data, source_column);
        // AI转markdown工具 _会变成\_，*会变成\*，需要替换掉
        md_data = md_data.replace("\\_", "_").replace("\\*", "*");
        log.info("首个sheet页数据：" + md_data);
//        columns_relation = replaceEnterChar();
        // BM25030518734 合并单元格问题
        // 配置markdown解析器（启用表格扩展）
        MutableDataSet options = new MutableDataSet();
        options.set(Parser.EXTENSIONS, List.of(TablesExtension.create()));
        Parser parser = Parser.builder(options).build();
        Node document = parser.parse(md_data);
        // 创建表格遍历器
        TableVisitor visitor = new TableVisitor();
        visitor.process(document);
        // 将markdown数据转为JSONArray
        JSONArray sourceDataList = visitor.mdDataToJson();
        if(sourceDataList == null) {
            return "转换异常：源数据markdown解析异常";
        }

        log.info("md转换成json后数据：" + sourceDataList.toStringPretty());

        // 判断是否有合并单元格
        boolean isMergedVertically = ExcelToJsonArray.isMergedVertically(filename, sourceDataList, source_column);
        // 若有合并单元格，则进行合并填充
        if(isMergedVertically) {
            log.info("有合并单元格");
            sourceDataList = ExcelToJsonArray.toJsonArray(filename, source_column);
            // 去掉头部非列名的行
            ExcelToJsonArray.deletNotTitleRow(sourceDataList, source_column);
            // 制造商、制造商型号 替代料处理
            ExcelToJsonArray.manufacturerMerge(sourceDataList, columns_relation);
            log.info("制造商、制造型号 替代料处理后数据：" + sourceDataList.toStringPretty());
        } else {
            // 制造商、制造商型号 替代料处理(未合并单元格，放在了新行)
            ExcelToJsonArray.manufacturerMerge2(sourceDataList, columns_relation);
            log.info("制造商、制造型号 替代料处理后数据2：" + sourceDataList.toStringPretty());
        }
        // 位号换行了，自动提到上一行处理
        margerLine(sourceDataList, columns_relation);
        log.info("margerLine后数据:"+ sourceDataList.toStringPretty());
        // 删除列数小于3的列
        deleteEmptyRow(sourceDataList);

        log.info("deleteEmptyRow后数据:"+ sourceDataList.toStringPretty());

        // 名称-物料名称 规格描述=型号+精度	封装=封装	备注=备注
        // 转换后的新数据行
        JSONArray newDataList = new JSONArray();
        // 列映射转对象
        JSONObject relationObj = JSONUtil.parseObj(columns_relation);
        // 列映射异常校验、去除
        checkConvert(relationObj, sourceDataList);
        for (Object sourceData : sourceDataList) {
            JSONObject newData = new JSONObject();
            JSONObject sourceDataObj = (JSONObject) sourceData;
            // 遍历列名映射
            for (String key : relationObj.keySet()) {
                String sourceValue = sourceDataObj.getStr(relationObj.getStr(key)); // 源值
                String sourceKey = relationObj.getStr(key); // 源列名
                if (StrUtil.isBlank(sourceKey) || "NaN".equals(sourceKey) // 未映射到源列名,标准列空列也要占位
                  || "NaN".equals(sourceValue)) { // 源值空，则目标值空
                    newData.set(key, "");
                    continue;
                }
                // 目标列由多个源列组合而成的情况，单个列名也适用
                String[] moreSourceColumns = sourceKey.split(",");
                String value = "";
                for (String moreSourceColumn : moreSourceColumns) {
                    String singleSourceValue = sourceDataObj.getStr(moreSourceColumn);
                    if (StrUtil.isBlank(singleSourceValue) || "NaN".equals(singleSourceValue)) {
                        continue;
                    }
                    value = value + singleSourceValue + ",";
                }
                if (value.length() > 0) {
                    value = value.substring(0, value.length() - 1);
                }
                newData.set(key, value);
            }
            // 将超出表头列的行数据放到备注里面
            ExcelToJsonArray.fillOutOfRangeData(sourceDataObj, newData);
            newDataList.add(newData);
        }
        // 补充提供方字段
        JSONArray providerCfg = getJsonArrayCfg("提供方关键字匹配.txt");
        ExcelToJsonArray.fillProviderFields(newDataList, providerCfg);
        // 写入新的Excel
        String excelResult = createWorkbookWithSheet(filename, newDataList);
        if(excelResult != null){
            return excelResult;
        }
        // 上传S3文件服务器
        String result = saveFile2S3(filename, userId, appKey);
        return result;
    }

    public String getTemplateContent(String bom_no, String source_coloum) {
        try {
            // 读取文件全部内容为字节数组，再转为字符串
            String content = new String(Files.readAllBytes(Paths.get(template + bom_no + ".txt")));
            content = content.replace("{客户列}", source_coloum);
            return content.toString();
        } catch (IOException e) {
            log.error("getTemplateContent", e);
            return "";
        }

    }

    public JSONObject getJsonObjCfg(String fileName) {
        try {
            // 读取文件全部内容为字节数组，再转为字符串
            String content = new String(Files.readAllBytes(Paths.get(template + fileName)));
            JSONObject result = JSONUtil.parseObj(content);
            return result;
        } catch (IOException e) {
            log.error("getErrorRelationContent", e);
            return null;
        }

    }

    /**
     *
     * @param fileName
     * @return
     */
    public JSONArray getJsonArrayCfg(String fileName) {
        try {
            // 读取文件全部内容为字节数组，再转为字符串
            String content = new String(Files.readAllBytes(Paths.get(template + fileName)));
            JSONArray result = JSONUtil.parseArray(content);
            return result;
        } catch (IOException e) {
            log.error("getJsonArrayCfg", e);
            return null;
        }
    }

    public String checkConvert(String columns_relation) {
        JSONObject errObj = new JSONObject();
        try {
            new JSONObject(columns_relation);
        } catch (JSONException ex1) {
            log.error("校验异常:columns_relation非json格式:{}", columns_relation);
            return "校验异常:columns_relation非json格式";
        }
        JSONObject cfgObj = getJsonObjCfg("映射建议.txt");
        JSONObject relationObj = JSONUtil.parseObj(columns_relation);
        // 错误映射示例
        JSONObject errorRelation = cfgObj.getJSONObject("错误映射示例");
        for (String key : errorRelation.keySet()) {
            String relationValue = relationObj.getStr(key, "");
            relationValue = ExcelToJsonArray.deleteSpecialChar(relationValue);
            String[] relationValues = relationValue.split(",");
            for (String value : relationValues) {
                if (errorRelation.getStr(key).contains("," + value + ",")) {
                    errObj.set(key, relationValue);
                }
            }

        }
        if (errObj.size() > 0) {
            return "校验异常:" + errObj.toStringPretty();
        } else {
            return "校验OK";
        }
    }

    public void analysis(String url,String idTo,String env) throws IOException {

        // 使用 Hutool 下载文件到本地
        String fileName = "downloaded_file.xlsx"; // 可以从 URL 或其他地方动态生成文件名
        File targetFile = new File(localFilePath, fileName);  // 指定文件保存路径

        // 下载文件
        HttpResponse downloadResponse = HttpUtil.createGet(url).execute();
        InputStream input = downloadResponse.bodyStream();
        org.apache.commons.io.FileUtils.copyInputStreamToFile(input, targetFile);


        HttpRequest request = HttpUtil.createRequest(Method.POST, uploadUrl);
        request.header("Authorization", "Bearer app-LoNoVU9qD7dibFrxv22NNxTu");
        request.header("Content-Type", "multipart/form-data");

        request.form("file", targetFile);
        request.form("type", "excel/[xls|xlsx]");
        request.form("user", "single_test");

        // 发送请求并获取响应
        HttpResponse response = request.execute();


        // 输出响应结果
        if (response.isOk()) {
            JSONObject jo = JSONUtil.parseObj(response.body());
            targetFile.delete();
            String id = jo.getStr("id");
            log.info("文件上传成功,id="+id);


            // 创建一个POST请求
            request = HttpUtil.createPost(workFlowUrl);
            Map<String, String> requestHeaders = new HashMap<>();
            requestHeaders.put("Authorization", "Bearer app-LoNoVU9qD7dibFrxv22NNxTu");
            requestHeaders.put("Content-Type", "application/json");
            request.addHeaders(requestHeaders);
            String requestBody = String.format("""
                {
                    "inputs": {
                    "cust_upload_file": {
                      "transfer_method": "local_file",
                      "upload_file_id": "%s",
                      "type": "document"
                    }
                  },
                    "response_mode": "streaming",
                    "user": "batch_test"
                }
                """, id);
            request.body(requestBody);




            // 执行请求并获取响应流
            try (InputStream inputStream = request.execute().bodyStream()) {
                // 将流式响应内容写入到本地文件
//                FileUtil.writeFromStream(inputStream, new File("D:\\SVN\\BomFileFormat\\master\\otherFiles\\tmp\\日志\\"+".txt"));
                String s = inputStreamToString(inputStream);
                log.info("s:"+s);
                String s1 = extractUrlFromOutputs(s);
                log.info("s1:"+s1);
                if(StringUtil.isNotBlank(s1)){


                    //测试环境
                    String api = "http://192.168.10.22:7066/api/yangpihuiAPI/AnalysisCallback";
                    if(StringUtil.isNotBlank(env)&&"prod".equals(env)){
                        api = "http://192.168.10.22:7055/api/yangpihuiAPI/AnalysisCallback";
                    }



                    // 请求的 body 数据，JSON 格式
                    String body = String.format("{\n" +
                            "    \"fileurl\":\"%s\",\n" +
                            "    \"id\":\"%s\"\n" +
                            "}", s1, idTo);

                    // 请求头部的 API-KEY
                    String apiKey = "421327dd-fa6a-40d2-a881-a3208376e417";
                    log.info("回调请求: " + body);
                    // 发起 POST 请求
                    HttpResponse res = HttpRequest.post(api)
                            .header("API-KEY", apiKey)  // 设置请求头
                            .body(body)  // 设置请求体
                            .execute();  // 执行请求

                    // 输出响应内容

                    log.info("回调结果: " + res.body());

                }


            } catch (Exception e) {
                e.printStackTrace();
            }



        } else {
            System.out.println("Failed to upload file: " + response.getStatus() + " " + response.body());
        }
    }


    public static String extractUrlFromOutputs(String input) {
        // 使用正则表达式提取 URL
        String regex = "\"outputs\": \\{[^}]*\"text\": \"[^\"]*?(https?://[^\"]+)\"";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        String url = null;

        if (matcher.find()) {
            // 获取匹配到的 URL
            url = matcher.group(1);  // 捕获组 1 是 URL
        }

        return url;  // 如果找到 URL，返回 URL，否则返回 null
    }


    public static String inputStreamToString(InputStream inputStream) throws IOException {
        StringBuilder result = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append("\n");
            }
        }
        return result.toString();
    }



}
